`
https://leetcode.cn/problems/lexicographically-smallest-permutation-greater-than-target/
`

/**
 * @param {string} s
 * @param {string} target
 * @return {string}
 */
var lexGreaterPermutation = function (s, target) {
  const n = s.length
  const counter = {}
  // 记录 counter 里的负数数量
  let negCount = 0
  // 将 counter 里的字符按字典序构建成字符串
  const buildStr = (counter) => {
    const res = []
    for (const c of 'abcdefghijklmnopqrstuvwxyz') {
      if (counter[c]) {
        res.push(c.repeat(counter[c]))
      }
    }
    return res.join('')
  }

  // 统计 s
  for (const c of s) {
    counter[c] = (counter[c] || 0) + 1
  }

  // 消耗掉 target
  for (const c of target) {
    const prev = counter[c] || 0
    counter[c] = prev - 1
    if (prev === 0) {
      negCount++
    }
  }

  // 从后面开始尝试
  for (let i = n - 1; i >= 0; i--) {
    const c = target[i]
    const prev = counter[c]
    // 撤销消耗
    counter[c] += 1
    if (prev === -1) {
      negCount--
    }
    // 如果有负数说明无法凑齐 s
    if (negCount > 0) continue

    // 找到，不断增大 target[i]
    for (let j = c.charCodeAt(0) - 'a'.charCodeAt(0) + 1; j < 26; j++) {
      const ch = String.fromCharCode(j + 'a'.charCodeAt(0))
      // ch 字符用完了
      if (!counter[ch]) continue

      // 找到答案，答案由三部分组成
      // 前面还没找的部分 + 找到的不断增大的字符 + counter 里剩下的字符按字典序排回去
      counter[ch] -= 1
      const res = target.substring(0, i) + ch + buildStr(counter)
      return res
    }
  }
  return ""
};